<!DOCTYPE html>
<!--
-- Copyright (c) 2012-2020 MIRACL UK Ltd.
--
-- This file is part of MIRACL Core
-- (see https://github.com/miracl/core).
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-->
<html>
<head>
<title>JavaScript Test ECC</title>
</head>
<body>
<h1>JavaScript Test ECC Examples</h1>
<script type="text/javascript"src=./../../src/rand.js></script>
<script type="text/javascript"src=./../../src/share.js></script>
<script type="text/javascript"src=./../../src/rom_curve.js></script>
<script type="text/javascript"src=./../../src/rom_field.js></script>
<script type="text/javascript"src=./../../src/uint64.js></script>
<script type="text/javascript"src=./../../src/aes.js></script>
<script type="text/javascript"src=./../../src/big.js></script>
<script type="text/javascript"src=./../../src/gcm.js></script>
<script type="text/javascript"src=./../../src/hmac.js></script>
<script type="text/javascript"src=./../../src/hash256.js></script>
<script type="text/javascript"src=./../../src/hash384.js></script>
<script type="text/javascript"src=./../../src/hash512.js></script>
<script type="text/javascript"src=./../../src/sha3.js></script>
<script type="text/javascript"src=./../../src/nhs.js></script>
<script type="text/javascript"src=./../../src/fp.js></script>
<script type="text/javascript"src=./../../src/ff.js></script>
<script type="text/javascript"src=./../../src/rsa.js></script>
<script type="text/javascript"src=./../../src/ecp.js></script>
<script type="text/javascript"src=./../../src/ecdh.js></script>
<script type="text/javascript"src=./../../src/hpke.js></script>
<script type="text/javascript"src=./../../src/ctx.js></script>


<p><a id="myLink1" href="#" onclick="ED25519();">ED25519 Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink2" href="#" onclick="NIST256();">NIST256 Weierstrass Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink3" href="#" onclick="GOLDILOCKS();">GOLDILOCKS Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink8" href="#" onclick="RSA2048();">RSA2048 RSA Key generation/Encryption/Decryption</a></p>


<script>

/* Test ECC */
/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */

// ED25519 context
function ED25519() {
	var ctx = new CTX('ED25519');

	var mywindow=window.open();

	mywindow.document.write("<br> ED25519 Curve "+  "<br>");

	var i,res;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	var RAW=[];
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
// private key S0 of size EGS bytes derived from Password and Salt 
	var S0=ctx.HMAC.PBKDF2(ctx.HMAC.MC_SHA2, sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
// Generate Key pair S/W 
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
// Random private key for other party 
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

// Calculate common key using DH - IEEE 1363 method 

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0,0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1,0);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.HMAC.KDF2(ctx.HMAC.MC_SHA2, sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	} 
}
// NIST256 context

function NIST256() {
	var ctx = new CTX('NIST256');
	var mywindow=window.open();

	mywindow.document.write("<br> NIST256 Curve "+  "<br>");
	var i,res;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	var RAW=[];
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);


	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
// private key S0 of size EGS bytes derived from Password and Salt 
	var S0=ctx.HMAC.PBKDF2(ctx.HMAC.MC_SHA2, sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
// Generate Key pair S/W 
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
// Random private key for other party 
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

// Calculate common key using DH - IEEE 1363 method 

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0,0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1,0);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.HMAC.KDF2(ctx.HMAC.MC_SHA2, sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	}

}


// GOLDILOCKS context
function GOLDILOCKS() {
	var ctx = new CTX('GOLDILOCKS');
	var mywindow=window.open();

	mywindow.document.write("<br> GOLDILOCKS Curve "+  "<br>");

	var i,res;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);


	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
// private key S0 of size EGS bytes derived from Password and Salt 
	var S0=ctx.HMAC.PBKDF2(ctx.HMAC.MC_SHA2, sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
// Generate Key pair S/W 
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
// Random private key for other party 
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

// Calculate common key using DH - IEEE 1363 method 

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0,0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1,0);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.HMAC.KDF2(ctx.HMAC.MC_SHA2, sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	}
}


// Test RSA 
// test driver and function exerciser for RSA API Functions 


// RSA2048 context
function RSA2048() {
	var ctx = new CTX('RSA2048');

	var i,j=0;

	var sha=ctx.RSA.HASH_TYPE;

	var message="Hello World\n";

	var pub=new ctx.rsa_public_key(ctx.FF.FFLEN);
	var priv=new ctx.rsa_private_key(ctx.FF.HFLEN);

	var ML=[];
	var C=[];
	var S=[];
	
	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

	var mywindow=window.open();

	var start,end,time;
	start=new Date().getTime();
	mywindow.document.write("<br> Generating RSA public/private key pair (slow!)  <br>");
	ctx.RSA.KEY_PAIR(rng,65537,priv,pub);
	end=new Date().getTime();
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	var M=ctx.RSA.stringtobytes(message);  
	mywindow.document.write("Encrypting test string <br>");

	var E=ctx.HMAC.OAEP_ENCODE(sha,M,rng,null,ctx.RSA.RFS); // OAEP encode message m to e  
	mywindow.document.write("Encoding= 0x" + ctx.RSA.bytestohex(E) + "<br>");  

	mywindow.document.write("Public key= 0x"+pub.n.toString() + "<br>"); 

	start=new Date().getTime();	
	ctx.RSA.ENCRYPT(pub,E,C);     // encrypt encoded message 
	end=new Date().getTime();	
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	mywindow.document.write("Ciphertext= 0x" + ctx.RSA.bytestohex(C) + "<br>");  

	mywindow.document.write("Decrypting test string <br>");
	start=new Date().getTime();	
	ctx.RSA.DECRYPT(priv,C,ML); 
	end=new Date().getTime();
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	var cmp=true;
	if (E.length!=ML.length) cmp=false;
	else
	{
		for (var j=0;j<E.length;j++)
			if (E[j]!=ML[j]) cmp=false;
	}
	if (cmp) mywindow.document.write("Decryption is OK <br>");
	else mywindow.document.write("Decryption Failed <br>");

	var MS=ctx.HMAC.OAEP_DECODE(sha,null,ML,ctx.RSA.RFS); // OAEP decode message  
	mywindow.document.write("Decoding= 0x" + ctx.RSA.bytestohex(MS) + "<br>");  

	mywindow.document.write("message= "+ctx.RSA.bytestostring(MS) + "<br>");  


   var T=ctx.HMAC.PSS_ENCODE(sha,M,rng,ctx.RSA.RFS);
   //mywindow.document.write("T= 0x"+ctx.RSA.bytestohex(T) + "<br>"); 

   if (ctx.HMAC.PSS_VERIFY(sha,M,T))
        mywindow.document.write("PSS Encoding OK <br>");
    else
        mywindow.document.write("PSS Encoding FAILED <br>");


	mywindow.document.write("Signing message <br>");
	ctx.HMAC.PKCS15(sha,M,C,ctx.RSA.RFS);

	ctx.RSA.DECRYPT(priv,C,S); // create signature in S  

	mywindow.document.write("Signature= 0x" + ctx.RSA.bytestohex(S) + "<br>");  

	ctx.RSA.ENCRYPT(pub,S,ML); 

	cmp=true;
	if (C.length!=ML.length) cmp=false;
	else
	{
		for (var j=0;j<C.length;j++)
			if (C[j]!=ML[j]) cmp=false;
	}
	if (cmp) mywindow.document.write("Signature is valid <br>");
	else mywindow.document.write("Signature is INVALID <br>");

	ctx.RSA.PRIVATE_KEY_KILL(priv);
}

</script>
</body>
</html>
